﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using eWallet.Data.Local;
using eWallet.Data.Local.eWalletDataSetTableAdapters;
using System.Diagnostics;
using System.IO;
using Microsoft.Win32;
using eWallet.Security.Cryptography;
using System.Collections;

namespace eWallet
{
	/// <summary>
	/// Interaction logic for SecretWindow.xaml
	/// </summary>
	public partial class SecretWindow : Window
	{

		private eWalletDataSet DataSet = new eWalletDataSet();

		public SecretWindow()
		{
			InitializeComponent();
			this.PopulateGroups();
			this.ContentTypeCombo.SelectedIndex = 0;
		}


		public ICryptoModule DecryptionModule { get; set; }

		private eWalletDataSet.SecretsRow _SelectedSecret;
		public eWalletDataSet.SecretsRow SelectedSecret
		{
			get { return _SelectedSecret; }
			set
			{
				_SelectedSecret = value;

				#region Clear dialog to its default settings

				this.GroupCombo.SelectedIndex = -1;
				this.ContentTypeCombo.SelectedIndex = -1;
				this.ContentTypeTextbox.Text = string.Empty;
				this.DescriptionTextbox.Text = string.Empty;
				this.PlainTextTextbox.Text = string.Empty;
				this.FileNameTextBox.Text = string.Empty;
				this.FilePathTextbox.Text = string.Empty;
				this.TagsTextbox.Text = string.Empty;

				#endregion

				if (null != _SelectedSecret)
				{
					this.ContentTypeTextbox.Text = _SelectedSecret.ContentType;
					this.DescriptionTextbox.Text = _SelectedSecret.IsDescriptionNull() ? "" : _SelectedSecret.Description;

                    foreach (ComboBoxItem group in this.GroupCombo.Items)
                    {
                        var id = (Guid)group.Tag;
                        if (id == _SelectedSecret.GroupId)
                        {
                            group.IsSelected = true;
                            break;
                        }
                    }

                    List<string> tagLabels = new List<string>();
                    foreach (var tagLink in _SelectedSecret.GetSecretsTagsRows())
                    {
                        tagLabels.Add(tagLink.TagsRow.Label);
                    }
                    tagLabels.Sort();
                    this.TagsTextbox.Text = string.Join(";", tagLabels.ToArray());

                    if (_SelectedSecret.IsFileNameNull() || string.IsNullOrEmpty(_SelectedSecret.FileName))
					{
						// Plain text
						this.FileNameTextBox.Text = string.Empty;
					}
					else
					{
						// File
						this.FileNameTextBox.Text = _SelectedSecret.FileName;
					}

				}
			}
		}

		public int SelectedTabIndex { get; set; }

		public IEnumerable<string> SelectedTags { get; set; }



		protected override void OnClosed(EventArgs e)
		{
			try
			{
				this.DataSet.Dispose();
			}
			catch { }
			base.OnClosed(e);
		}

		protected override void OnRender(DrawingContext drawingContext)
		{

			if (this.SelectedTabIndex > -1 && this.SelectedTabIndex < 3)
			{
				this.MainTab.SelectedIndex = this.SelectedTabIndex;
			}

			base.OnRender(drawingContext);
		}



		private eWalletDataSet.GroupsRow GetSelectedGroup()
		{
			if (this.GroupCombo.SelectedIndex >= 0)
			{
				ComboBoxItem item = (ComboBoxItem)this.GroupCombo.SelectedItem;
				Guid id = (Guid)item.Tag;
				return this.DataSet.Groups.FirstOrDefault(row => row.Id == id);
			}
			return null;
		}

		private void PopulateGroups()
		{
			using (GroupsTableAdapter adr = new GroupsTableAdapter(Properties.Settings.Default.DatabasePath))
			{
				adr.ClearBeforeFill = true;
				adr.Fill(this.DataSet.Groups);
			}

			this.GroupCombo.Items.Clear();
			foreach (var group in this.DataSet.Groups)
			{
				ComboBoxItem item = new ComboBoxItem();
				item.Content = group.Name;
				item.Tag = group.Id;
				if (!group.IsDescriptionNull())
					item.ToolTip = group.Description;

				this.GroupCombo.Items.Add(item);
			}

			if (this.GroupCombo.Items.Count > 0)
				this.GroupCombo.SelectedIndex = 0;
		}

		private void OKButton_Click(object sender, RoutedEventArgs e)
		{

			#region Input checking

			if (this.GroupCombo.SelectedIndex < 0)
			{
				MessageBox.Show("No group is selected. Cannot protected the data.", "No Group", MessageBoxButton.OK, MessageBoxImage.Error);
				this.MainTab.SelectedItem = this.GroupTabItem;
				this.GroupCombo.Focus();
				return;
			}

			if (this.ContentTypeCombo.SelectedIndex == 0)
			{
				// Plain text
				if (string.IsNullOrEmpty(this.PlainTextTextbox.Text) || this.PlainTextTextbox.Text.Trim().Length == 0)
				{
					MessageBox.Show(this, "You did not specify any secret text to protect.", "Missing Text", MessageBoxButton.OK, MessageBoxImage.Error);
					this.MainTab.SelectedItem = this.SecretDataTabItem;
					this.PlainTextTextbox.Focus();
					return;
				}

			}
			else if (this.ContentTypeCombo.SelectedIndex == 1)
			{
				// File
				if (string.IsNullOrEmpty(this.FilePathTextbox.Text))
				{
					MessageBox.Show(this, "You did not select any file as the content for your secret.", "No File", MessageBoxButton.OK, MessageBoxImage.Error);
					this.MainTab.SelectedItem = this.SecretDataTabItem;
					return;
				}

				if (!File.Exists(this.FilePathTextbox.Text))
				{
					MessageBox.Show(this, string.Format("The file '{0}' you selected does not exist. Please select an existing file.", this.FilePathTextbox.Text), "File Not Found", MessageBoxButton.OK, MessageBoxImage.Error);
					this.MainTab.SelectedItem = this.SecretDataTabItem;
					return;
				}
			}

			if (null == this.TagsTextbox.Text || this.TagsTextbox.Text.Trim().Length == 0)
			{
				var result = MessageBox.Show(this, "You have not specified any tags for your secret. Click 'OK' to save anyway or 'Cancel' to return to the window and specify tags.", "Missing Tags", MessageBoxButton.OKCancel, MessageBoxImage.Warning);
				if (result == MessageBoxResult.Cancel)
				{
					this.MainTab.SelectedItem = this.MetaDataTabItem;
					this.TagsTextbox.Focus();
					return;
				}
			}

			#endregion

			var group = this.GetSelectedGroup();
			if (null == group.BlobsRow && null == this.DataSet.Blobs.FirstOrDefault(b=>b.Id == group.EncryptedKeyBlobId))
			{
				using (TableAdapterManager tam = new TableAdapterManager(Properties.Settings.Default.DatabasePath))
				{
					tam.BlobsTableAdapter.ClearBeforeFill = false;
					tam.BlobsTableAdapter.Fill(this.DataSet.Blobs, group.EncryptedKeyBlobId);
				}
			}

			var module = CryptoModuleFactory.GetCryptoModule(group);

			if(null != module)
			{

				this.SelectedSecret.ContentType = this.ContentTypeTextbox.Text;
				if (!string.IsNullOrEmpty(this.FileNameTextBox.Text))
				{
					this.SelectedSecret.FileName = this.FileNameTextBox.Text;
				}
				else
				{
					this.SelectedSecret.SetFileNameNull();
				}
				this.SelectedSecret.Description = this.DescriptionTextbox.Text;
				this.SelectedSecret.GroupId = group.Id;
				this.SelectedSecret.LastModified = DateTime.UtcNow;
				this.SelectedSecret.LastModifiedBy = string.Format(@"{0}\{1}", Environment.UserDomainName, Environment.UserName);
				var tags = this.TagsTextbox.Text.Split(';').ToList();
				List<string> list = new List<string>();
				foreach (string s in tags)
				{
					if (!string.IsNullOrEmpty(s) && s.Trim().Length > 0)
					{
						list.Add(s.Trim());
					}
				}
				this.SelectedTags = list;


				if (this.ContentTypeCombo.SelectedIndex == 0)
				{
					// Plain text.
					this.SelectedSecret.EncryptData(this.PlainTextTextbox.Text, module, group);
				}
				else if (this.ContentTypeCombo.SelectedIndex == 1)
				{
					// File.

				}


				this.DialogResult = true;
				this.Close();
			}
		}

		private void CancelButton_Click(object sender, RoutedEventArgs e)
		{
			this.DialogResult = false;
			this.Close();
		}

		private void ContentTypeCombo_SelectionChanged(object sender, SelectionChangedEventArgs e)
		{
			this.SecretTabLayoutGrid.RowDefinitions[2].Height = new GridLength(0, GridUnitType.Pixel);
			this.PlainTextGroup.Visibility = Visibility.Collapsed;
			this.SecretTabLayoutGrid.RowDefinitions[3].Height = new GridLength(0, GridUnitType.Pixel);
			this.FileGroup.Visibility = Visibility.Collapsed;

			if (this.ContentTypeCombo.SelectedIndex == 0)
			{
				this.SecretTabLayoutGrid.RowDefinitions[2].Height = new GridLength(double.MaxValue, GridUnitType.Star);
				this.PlainTextGroup.Visibility = Visibility.Visible;

				this.ContentTypeTextbox.Text = System.Net.Mime.MediaTypeNames.Text.Plain;
				this.FileNameTextBox.Text = string.Empty;
			}
			else if (this.ContentTypeCombo.SelectedIndex == 1)
			{
				this.SecretTabLayoutGrid.RowDefinitions[3].Height = new GridLength(double.MaxValue, GridUnitType.Star);
				this.FileGroup.Visibility = Visibility.Visible;

				this.ContentTypeTextbox.Text = string.Empty;
				this.FilePathTextbox.Text = string.Empty;

				string s = this.FilePathTextbox.Text;
				this.FilePathTextbox.Text = string.Empty;
				this.FilePathTextbox.Text = s;
			}
		}

		private void BrowseFileButton_Click(object sender, RoutedEventArgs e)
		{
			OpenFileDialog dlg = new OpenFileDialog();
			dlg.CheckFileExists = true;
			dlg.Filter = "All Files (*.*)|*.*";
			dlg.Title = "Select File";
			var result = dlg.ShowDialog(this);
			if (result.HasValue && result.Value)
			{
				this.FilePathTextbox.Text = dlg.FileName;
			}
		}

		private void FilePathTextbox_TextChanged(object sender, TextChangedEventArgs e)
		{
			if (!string.IsNullOrEmpty(this.FilePathTextbox.Text))
			{
				FileInfo fi = new FileInfo(this.FilePathTextbox.Text);

				this.FileNameTextBox.Text = fi.Name;

				var rootKey = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(fi.Extension);
				if (null != rootKey)
				{
					var val = rootKey.GetValue("Content Type", System.Net.Mime.MediaTypeNames.Application.Octet) as string;
					this.ContentTypeTextbox.Text = val;
				}
				else
				{
					this.ContentTypeTextbox.Text = System.Net.Mime.MediaTypeNames.Application.Octet;
				}
			}
			else
			{
				this.ContentTypeTextbox.Text = string.Empty;
				this.FileNameTextBox.Text = string.Empty;
			}

		}

	}
}
